home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NOVA - For the NeXT Workstation
/
NOVA - For the NeXT Workstation.iso
/
SourceCode
/
GaugesDemo
/
Gauge.m
< prev
next >
Wrap
Text File
|
1992-12-19
|
11KB
|
463 lines
/* Generated by Interface Builder */
#import "Gauge.h"
#import <appkit/graphics.h>
#import <appkit/Window.h>
#define GAUGEQUANTTICS \
if (GaugeDat.ticQuanta){ \
GaugeDat.ticSize = \
(((int)(GaugeDat.ticSize/GaugeDat.ticQuanta))+1) \
*GaugeDat.ticQuanta; \
GaugeDat.startValue = \
(((int)(GaugeDat.startValue/GaugeDat.ticSize))-1) \
*GaugeDat.ticSize; \
}
@implementation Gauge
/**********************************************************************/
/* Factory Methods
/**********************************************************************/
+ newFrame: (NXRect *) r
{
self = [super newFrame:r];
GaugeDat.backGray = NX_LTGRAY;
GaugeDat.faceGray = NX_WHITE;
GaugeDat.ticGray = NX_BLACK;
GaugeDat.textGray = NX_BLACK;
GaugeDat.ptGray = NX_DKGRAY;
[self changeBMSize];
GaugeDat.startValue = 0.0;
GaugeDat.ticSize = 0.1;
GaugeDat.value = 0.5;
GaugeDat.numMajor = 11;
GaugeDat.numMinor = 1;
GaugeDat.ticQuanta = 0.0; /* tic can be any size */
GaugeDat.aThreshHi = 0.9;
GaugeDat.aThreshLo =0.1;
GaugeDat.labelTicPat = "%1.1f"; /* one sig dig on each side */
GaugeDat.ticFontName = "Helvetica";
GaugeDat.titleFontName = "Helvetica";
GaugeFlags.titleOn = NO;
GaugeFlags.ticsOn = YES;
GaugeFlags.labelTicsOn = NO;
GaugeFlags.autoScaleOn = YES;
GaugeFlags.jumpChange = YES;
GaugeFlags.overFlow = NO;
GaugeFlags.autoRenderBit = YES; /*always re render on changes */
GaugeFlags.borderType = NX_NOBORDER;
return self;
}
/**********************************************************************/
/* Private Methods
/**********************************************************************/
- reScaleGauge:sender
/* return self if overrun or rescale
/* else return nil;
/* This gets called if value is out of thresholds and auto scale is on.
/*
/* Autoscaling with no labels will cause the number of tics to change
/* when blowing up or shrinking tic mark values otherwise ...
/*
/* This will rescale the tic marks or start values under thse rules
/* Underrun:
/* if .aThreshLo > 0.0
/* then move low point so we are centered
/* else if aThreshHi < 1.0
/* then rescale tic marks to blow up
/*
/* Overrun
/* if .aThreshHi < 1.0
/* then move the tic marks to shrink
/* else if .aThreshLo > 0.0
/* then move up low so this is centered
/*
/* Bugs
/* no way to tell it fixed increment scaling
/* no wayt to autoscale and cap
/*
/* */
{
double tStart;
double tSize;
GaugeFlags.overFlow = NO;
if ((GaugeDat.value < GAUGEHI) && (GaugeDat.value > GAUGELO))
return nil;
/* if not autoscaling or both bounds locked then ... */
if (!GaugeFlags.autoScaleOn ||
((GaugeDat.aThreshLo <= 0.0) && (GaugeDat.aThreshHi >= 1.0))){
if ((GaugeDat.value < GAUGELO) || (GaugeDat.value > GAUGEHI)){
GaugeFlags.overFlow = YES;
if (GaugeDat.value > GAUGEMAX) GaugeDat.value = GAUGEMAX;
else if (GaugeDat.value < GaugeDat.startValue)
GaugeDat.value = GaugeDat.startValue;
[self sendAction:action to:target];
return self;
} else return nil;
}
/* we know we have at least one valid threshold if we got this far */
/* and we have an overrun or underrun condition */
if (GaugeDat.value > GAUGEHI){ /* overrun */
if (!GaugeFlags.labelTicsOn){
GaugeDat.numMajor += GaugeDat.numMajor -1 ;
}else if (GaugeDat.aThreshHi < 1.0){ /* scale tics */
GaugeDat.ticSize = GAUGESIZE*2 / (GaugeDat.numMajor-1);
}else{ /* move start */
GaugeDat.startValue += GAUGESIZE / 2;
}
}else{ /* underrun */
if (!GaugeFlags.labelTicsOn ){
if (GaugeDat.numMajor > 2)
GaugeDat.numMajor=((GaugeDat.numMajor-1)/2)+1;
}else if (GaugeDat.aThreshLo > 0.0){ /*move the start down */
GaugeDat.startValue -= GAUGESIZE / 2;
}else{ /* change tic size */
GaugeDat.ticSize = GAUGESIZE/2 / (GaugeDat.numMajor-1);
}
}
GAUGEQUANTTICS
return self;
}
/**********************************************************************/
/* Public Methods
/**********************************************************************/
- changeBMSize
{
NXRect r;
[self getBounds:&r];
if (GaugeDat.bm) [GaugeDat.bm free];
// Create offscreen window for face. Note that the defer: argument
// has to be NO for windows which will remain offscreen. Deferred
// windows only get created on a orderFront: (or any other method
// that causes them to come on screen).
GaugeDat.bm = [Window newContent:&r
style:NX_PLAINSTYLE
backing:NX_RETAINED
buttonMask:0
defer:NO];
GaugeDat.bmgState = (int)[GaugeDat.bm gState];
CONDITIONAL_REFRESH;
return self;
}
- sizeTo:(NXCoord)tW :(NXCoord)tH
{
fprintf(stderr,"in sizeTo\n");
[self changeBMSize];
return self;
}
- refreshBackground:sender;
/* redraw the bitmap - subclasses should override */
/* Subclasses should re image the bitmap and then do [self display] */
{
[self display];
return self;
}
/*____________________________________________________________________*/
- setBackGray:(float)bg Face:(float)fg Tic:(float)tg Text:(float)teg
Point:(float)pg
{
GaugeFlags.autoRenderBit = NO;
[self setBackgroundGray:bg];
[self setFaceGray:fg];
[self setTicGray:tg];
[self setTextGray:teg];
GaugeFlags.autoRenderBit = YES;
CONDITIONAL_REFRESH;
[self setPointerGray:pg];
return self;
}
- setBackgroundGray:(float)tC
{
if ((tC > 1.0) || (tC < 0.0)) return nil;
GaugeDat.backGray = tC;
CONDITIONAL_REFRESH;
return self;
}
- setFaceGray:(float)tC
{
if ((tC > 1.0) || (tC < 0.0)) return nil;
GaugeDat.faceGray = tC;
CONDITIONAL_REFRESH;
return self;
}
- setTicGray:(float)tC
{
if ((tC > 1.0) || (tC < 0.0)) return nil;
GaugeDat.ticGray = tC;
if (GaugeFlags.ticsOn) CONDITIONAL_REFRESH;
return self;
}
- setTextGray:(float)tC
{
if ((tC > 1.0) || (tC < 0.0)) return nil;
GaugeDat.textGray = tC;
if (GaugeFlags.labelTicsOn || GaugeFlags.titleOn)
CONDITIONAL_REFRESH;
return self;
}
- setPointerGray:(float)tC
{
if ((tC > 1.0) || (tC < 0.0)) return nil;
GaugeDat.ptGray = tC;
[self display];
return self;
}
- (float)backgroundGray
{
return GaugeDat.backGray;
}
- (float)faceGray
{
return GaugeDat.faceGray;
}
- (float)ticGray
{
return GaugeDat.ticGray;
}
- (float)textGray
{
return GaugeDat.textGray;
}
- (float)pointerGray
{
return GaugeDat.ptGray;
}
/*____________________________________________________________________*/
- setLowThresh:(double)lT HighThresh:(double)hT AndQuanta:(double)qT
{
if ((lT < 1.0) && (lT >= 0.0)) GaugeDat.aThreshLo = lT;
if ((hT > 0.0) && (hT <= 1.0)) GaugeDat.aThreshHi = hT;
GaugeDat.ticQuanta = qT;
return self;
}
- setTic:(double)sTic AndStart:(double)aStart;
/* this is so we can do auto scale with only one bitmap redraw */
{
if (sTic <= 0.0) return nil;
GaugeDat.ticSize = sTic;
GaugeDat.startValue = aStart;
GAUGEQUANTTICS
if ((GaugeDat.value > GAUGEHI) || (GaugeDat.value < GAUGELO)){
[self reScaleGauge:self];
} else GaugeFlags.overFlow = NO;
CONDITIONAL_REFRESH;
return self;
}
- setTicSize:(double)sTic
{
[self setTic:sTic AndStart:GaugeDat.startValue];
return self;
}
- setStartValue:(double)aStart
{
[self setTic:GaugeDat.ticSize AndStart:aStart];
return self;
}
- setDoubleValue:(double)aD
/* if autoscale and out of range then do it ... else load value and display */
{
GaugeDat.value = aD;
if ((aD <= GAUGELO) || (aD >= GAUGEHI)){
if ([self reScaleGauge:self] != nil)
CONDITIONAL_REFRESH;
else [self display];
}else{
GaugeFlags.overFlow = NO;
[self display];
}
return self;
}
- setFloatValue:(float)aF
{
[self setDoubleValue:(double)aF];
return self;
}
- takeDoubleValueFrom:sender;
{
[self setDoubleValue:[sender doubleValue]];
return self;
}
- takeFloatValueFrom:sender;
{
[self setDoubleValue:(double)[sender floatValue]];
return self;
}
- (double)maxValue
{
return GAUGEMAX;
}
- (double)ticSize
{
return GaugeDat.ticSize;
}
- (double)startValue
{
return GaugeDat.startValue;
}
- (double)doubleValue
{
return GaugeDat.value;
}
- (float)floatValue
{
return (float)GaugeDat.value;
}
- (BOOL)overFlowDetected
{
return GaugeFlags.overFlow;
}
/*____________________________________________________________________*/
- setMajorTics:(int)nTic
{
if (nTic <= 1) return nil;
GaugeDat.numMajor = nTic;
CONDITIONAL_REFRESH;
return self;
}
- setMinorTics:(int)nTic
{
if (nTic < 0) return nil;
GaugeDat.numMinor = nTic;
CONDITIONAL_REFRESH;
return self;
}
- setTitle:(char *)nTitle
{
GaugeDat.title = nTitle;
CONDITIONAL_REFRESH;
return self;
}
- (int)majorTics
{
return GaugeDat.numMajor;
}
- (int)minorTics
{
return GaugeDat.numMinor;
}
- (char *)title
{
return GaugeDat.title;
}
/*____________________________________________________________________*/
- setTitleEnable:(BOOL)aFlag
{
if (aFlag == GaugeFlags.titleOn) return nil;
GaugeFlags.titleOn = aFlag;
CONDITIONAL_REFRESH;
return self;
}
- setTicsEnable:(BOOL)aFlag
{
if (aFlag == GaugeFlags.ticsOn) return nil;
GaugeFlags.ticsOn = aFlag;
CONDITIONAL_REFRESH;
return self;
}
- setLabelTicsEnable:(BOOL)aFlag
{
if (aFlag == GaugeFlags.labelTicsOn) return nil;
GaugeFlags.labelTicsOn = aFlag;
CONDITIONAL_REFRESH;
return self;
}
- setAutoScaleEnable:(BOOL)aFlag
{
GaugeFlags.autoScaleOn = aFlag;
return self;
}
- setJumpChangeEnable:(BOOL)aFlag
{
GaugeFlags.jumpChange = aFlag;
return self;
}
- setBorderType:(int)aType
{
if ( (aType == NX_NOBORDER) || (aType == NX_LINE) ||
(aType == NX_BEZEL) || (aType == NX_RIDGE)){
GaugeFlags.borderType = aType;
CONDITIONAL_REFRESH;
}
return self;
}
- (BOOL)titleEnabled;
{
return GaugeFlags.titleOn;
}
- (BOOL)ticsEnabled
{
return GaugeFlags.ticsOn;
}
- (BOOL)labelTicsEnabled
{
return GaugeFlags.labelTicsOn;
}
- (BOOL)autoScaleEnabled
{
return GaugeFlags.autoScaleOn;
}
- (BOOL)jumpChangeEnabled
{
return GaugeFlags.jumpChange;
}
- (int)borderType
{
return GaugeFlags.borderType;
}
/*____________________________________________________________________*/
- awake
{
NXRect r;
[self getBounds:&r];
return [self changeBMSize];
}
- read:(NXTypedStream*)aStream
{
fprintf(stderr,"Gauge.m read:\n");
[super read:aStream];
NXReadTypes(aStream,"{ii}",&GaugeFlags);
NXReadTypes(aStream,"{fffff@idddiiddd****}",&GaugeDat);
NXReadTypes(aStream,"@:",&target,&action);
return self;
}
- write:(NXTypedStream*)aStream
{
fprintf(stderr,"Gauge.m: write:\n");
[super write:aStream];
NXWriteTypes(aStream,"{ii}",&GaugeFlags);
NXWriteTypes(aStream,"{fffff@idddiiddd****}",&GaugeDat);
NXWriteTypes(aStream,"@:",&target,&action);
return self;
}
/* I wish the control class would do this automaticlly */
- setTarget:aTarget { target = aTarget; return self; }
- setAction:(SEL)anAction { action = anAction; return self; }
@end